package com.shelpe.services.algorithm.client;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonFormat.Shape;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.shelpe.services.algorithm.client.SinbadClient.SinbadClientFallback;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@FeignClient(name = "${feign.sinbadserver.name}", url = "${feign.sinbadserver.url}", fallback = SinbadClientFallback.class)
public interface SinbadClient {

	@RequestMapping(method = RequestMethod.GET, path = "/sinbadservice/users/{userId}/keywords/{keywordId}/data", consumes = "application/json;charset=UTF-8")
	RptKeyword keywordData(@PathVariable("userId") Long userId, @PathVariable("keywordId") Long keywordId);

	@RequestMapping(method = RequestMethod.GET, path = "/sinbadservice/adgroups/{adgroup_id}/keywords/{keyword_id}", consumes = "application/json;charset=UTF-8")
	Keyword findKeyword(@PathVariable("adgroup_id") long adgroupID, @PathVariable("keyword_id") long keywordID);

	@RequestMapping(method = RequestMethod.POST, path = "sinbadservice/users/{user_id}/messages", consumes = "application/json;charset=UTF-8")
	MessageDto createMessage(@PathVariable("user_id") long userID, @RequestBody MessageDto dto);

	@Data
	@JsonInclude(Include.NON_DEFAULT)
	public class MessageDto {
		@JsonProperty("user_id")
		private long userID;
		private String nick;
		@JsonProperty("container_id")
		private long containerID;
		@JsonProperty("content_type")
		private String type;
		@JsonProperty("content")
		private String content;

		@JsonProperty("container_url")
		private String containerUrl;
	}

	@Data
	public class RptKeyword {
		private Long keywordId;
		private Date date;
		private Byte source;
		private Byte searchType;
		private Long adgroupId;
		private Long taobaoUserId;
		private Long campaignId;
		private Float cpc;
		private Float ctr;
		private Integer impressions;
		private Float cpm;
		private Integer click;
		private Integer cost;
		private Float avgpos;
		private Integer directPay;
		private Integer indirectPay;
		private Integer directPayCount;
		private Integer indirectPayCount;
		private Integer favShopCount;
		private Integer favItemCount;
		private Integer directCartTotal;
		private String keywordstr;
		private Integer indirectCartTotal;
		private Integer cartTotal;
		private Integer qscore;
		private Integer wirelessQscore;
		private float cvr;
		private float roi;
		private float favCountRate;
		private float cartCountRate;
		private Integer payCount;
		private float sale;
	}

	@Data
	public class Keyword {
		@JsonProperty("keyword_id")
		private long keywordID;
		@JsonProperty("match_scope")
		private int matchScope;
		private String word;
		@JsonProperty("max_price")
		private int maxPrice;
		private int qscore;

		@JsonProperty("adgroup_id")
		private long adgroupID;
	}

	@RequestMapping(method = RequestMethod.POST, path = "/sinbadservice/adgroups", consumes = "application/json;charset=UTF-8")
	AdgroupDto createAdgroup(@RequestBody AdgroupDto dto);

	@Data
	public static class AdgroupResponse {
		@JsonProperty("adgroup_id")
		private long adgroupID;
		private boolean status;
	}

	@Data
	@JsonInclude(Include.NON_DEFAULT)
	public static class AdgroupDto {

		@JsonProperty("adgroup_id")
		private long adgroupID;

		@JsonProperty("user_id")
		private long userID;
		@JsonProperty("campaign_id")
		private long campaignID;
		@JsonProperty("product_id")
		private long productID;
		@JsonProperty("title")
		private String productName;
		@JsonProperty("img_url")
		private String productUrl;
		@JsonProperty("creative_title")
		private String creativeName;
		@JsonProperty("creative_img_url")
		private String creativeImgUrl;
		private int status = -1;
		@JsonProperty("drive_type")
		private int driveType;
		@JsonProperty("default_price")
		private int defaultPrice;

		private int limit;
		/**
		 * below fields are only for update
		 */
		@JsonProperty("line_status")
		private String lineStatus;

		@JsonProperty("maintainDate")
		@JsonFormat(shape = Shape.STRING, pattern = "yyyy-MM-dd")
		private Date maintainedDate;
		@JsonProperty("adjust_count")
		private int adjustCount;

		private SimbaProxyBaseDto.Error error;
	}

	@RequestMapping(method = RequestMethod.PUT, path = "/sinbadservice/adgroups/{adgroup_id}/@status", consumes = "application/json;charset=UTF-8")
	AdgroupDto updateAdgroupStatus(@PathVariable("adgroup_id") long adgroupID, @RequestBody AdgroupDto dto);

	@RequestMapping(method = RequestMethod.PUT, path = "/sinbadservice/adgroups/{adgroup_id}", consumes = "application/json;charset=UTF-8")
	AdgroupDto updateAdgroup(@PathVariable("adgroup_id") long adgroupID, @RequestBody AdgroupDto dto);

	@RequestMapping(method = RequestMethod.POST, path = "/sinbadservice/adgroups/{adgroup_id}/keywords", consumes = "application/json;charset=UTF-8")
	ListResponse<PricingKeyword> addKeywords(@PathVariable("adgroup_id") long adgroupID,@RequestBody List<HandlingKeyword> dtos);

	@Data
	@JsonInclude(Include.NON_DEFAULT)
	public class HandlingKeyword {
		private int matchScope = -1;
		private String word;
		private int maxPrice = -1;
		private int isDefaultPrice = -1;

		//只为返回
		@JsonProperty("keywordId")
		private long keywordID;
		private int maxMobilePrice = -1;
	}

	@RequestMapping(method = RequestMethod.POST, path = "/sinbadservice/users/{user_id}/keywords/@pricing", consumes = "application/json;charset=UTF-8")
	ListResponse<PricingKeyword> pricingKeywords(@PathVariable("user_id") long userID, @RequestBody List<PricingKeyword> dtos);

	@Data
	@JsonInclude(Include.NON_NULL)
	public class ListResponse<T> {
		private boolean status;
		private int total;
		private List<T> datas;
		
		private SimbaProxyBaseDto.Error error;
	}

	
	@Data
	@JsonInclude(Include.NON_DEFAULT)
	public class PricingKeyword {
		@JsonProperty("keywordId")
		private long keywordID;

		private int matchScope = -1;
		private String word;
		private int maxPrice = -1;
		private int isDefaultPrice = -1;
		private int maxMobilePrice = -1;
		private int mobileIsDefaultPrice = -1;
	}

	@RequestMapping(method = RequestMethod.DELETE, value = "/sinbadservice/campaigns/{campaignId}/keywords", consumes = "application/json;charset=UTF-8")
	ListResponse<PricingKeyword> delKeywords(@PathVariable("campaignId") long campaignID,
			@RequestParam("keywordIds") List<Long> keywordIDs);

	@Data
	@JsonInclude(Include.NON_DEFAULT)
	public static class CampaignDto {

		@JsonProperty("campaign_id")
		private long campaignID = -1;

		@JsonProperty("user_id")
		private long userID = -1;

		private int budget;

		private String title;
		private int autoType = -1;

		private Area area;

		private String schdule;

	}

	@Data
	public static class Area {
		private boolean asAll;
		private List<Integer> nums;

		public void addArea(int num) {
			if (this.nums == null) {
				this.nums = new ArrayList<Integer>();
			}
			this.nums.add(num);
		}
	}

	@RequestMapping(method = RequestMethod.PUT, path = "/sinbadservice/campaigns/{campaign_id}", consumes = "application/json;charset=UTF-8")
	CampaignDto updateCampaign(@PathVariable("campaign_id") long campaignID, @RequestBody CampaignDto dto);

	@Service
	@Slf4j
	public static class SinbadClientFallback implements SinbadClient {

		@Override
		public Keyword findKeyword(long adgroupID, long keywordID) {
			log.error("fallback findKeyword: {}, {}", adgroupID, keywordID);
			return new Keyword();
		}

		@Override
		public AdgroupDto createAdgroup(AdgroupDto dto) {
			log.error("fallback createAdgroup: {}", dto);
			return new AdgroupDto();
		}

		@Override
		public AdgroupDto updateAdgroupStatus(long adgroupID, AdgroupDto dto) {
			log.error("fallback updateAdgroupStatus: {}, {}", adgroupID, dto);
			return new AdgroupDto();
		}

		@Override
		public ListResponse<PricingKeyword> addKeywords(long userID, List<HandlingKeyword> dtos) {
			log.error("fallback addKeywords: {}, {}", userID, dtos);
			ListResponse<PricingKeyword> res = new ListResponse<PricingKeyword>();
			res.setDatas(new ArrayList<PricingKeyword>());
			res.setError(new SimbaProxyBaseDto.Error());
			res.getError().setCode(-1);
			res.getError().setMessage("fallback");
			return res;
		}

		@Override
		public ListResponse<PricingKeyword> pricingKeywords(long adgroupID, List<PricingKeyword> dtos) {
			log.error("fallback pricingKeyword: {}, {}", adgroupID, dtos);
			ListResponse<PricingKeyword> res = new ListResponse<PricingKeyword>();
			res.setDatas(new ArrayList<PricingKeyword>());
			res.setError(new SimbaProxyBaseDto.Error());
			res.getError().setCode(-1);
			res.getError().setMessage("fallback");
			return res;
		}

		@Override
		public ListResponse<PricingKeyword> delKeywords(long campaignID, List<Long> keywordIDs) {
			log.error("fallback delKeywords: {}, {}", campaignID, keywordIDs);
			ListResponse<PricingKeyword> res = new ListResponse<PricingKeyword>();
			res.setDatas(new ArrayList<PricingKeyword>());
			res.setError(new SimbaProxyBaseDto.Error());
			res.getError().setCode(-1);
			res.getError().setMessage("fallback");
			return res;
		}

		@Override
		public AdgroupDto updateAdgroup(long adgroupID, AdgroupDto dto) {
			log.error("fallback updateAdgroup: {}, {}", adgroupID, dto);
			return new AdgroupDto();
		}

		@Override
		public CampaignDto updateCampaign(long campaignID, CampaignDto dto) {
			log.error("fallback updateCampaign: {}, {}", campaignID, dto);
			return new CampaignDto();
		}

		@Override
		public RptKeyword keywordData(Long userId, Long keywordId) {
			log.error("fallback keywordData: {}, {}", userId, keywordId);
			return new RptKeyword();
		}

		@Override
		public MessageDto createMessage(long userID, MessageDto dto) {
			log.error("fallback keywordData: {}, {}", userID, dto);
			return new MessageDto();
		}
	}
}
